package com.huawang.mdesign.model.service.controller;

import com.huawang.business.dto.ModifyPropertyDTO;
import com.huawang.business.vo.ModelResultVo;
import com.huawang.business.vo.PropertyInfoVo;
import com.huawang.business.constants.ParamErrorConstants;
import com.huawang.mdesign.model.service.dto.*;
import com.huawang.mdesign.model.service.vo.*;
import com.huawang.mdesign.model.service.inter.PropertyGroupService;
import com.huawang.business.util.ValidateDataUtil;
import com.huawang.mdesign.model.service.inter.override.UAFPropertyManager;


import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Set;

@Tag(name = "属性分组")
@RestController
@Validated
@RequestMapping("/property/group/")
public class PropertyGroupController {

    @Autowired
    private PropertyGroupService propertyGroupService;

    @Autowired
    private UAFPropertyManager propertyManager;

    /**
     * 查询模型应用的约束列表
     *
     * @param projectId
     * @param instanceId
     * @return
     */
    @Operation(summary = "查询模型应用的约束列表")
    @GetMapping("/queryApplyConstraints")
    public BaseResponse<List<String>> queryApplyConstraints(String projectId,
                                                            @Parameter(name = "约束的模型id") String instanceId) {
        return BaseResponse.success(propertyGroupService.queryApplyConstraints(projectId, instanceId));
    }

    @Operation(summary = "批量查询模型应用的约束列表")
    @PostMapping("/queryElementApplyConstraints")
    public BaseResponse<List<ElementApplyConstraintVo>> queryElementApplyConstraints(@Valid @RequestBody QueryModelDTO queryModelDto) {
        return BaseResponse.success(propertyGroupService.queryElementApplyConstraints(queryModelDto.getProjectId(),
                queryModelDto.getInstanceIds()));
    }

    @Operation(summary = "查询项目中的约束及其约束元素")
    @GetMapping("/queryAllConstraintAndConstrainedElements")
    public BaseResponse<List<ElementApplyConstraintVo>> queryAllConstraintAndConstrainedElements(String projectId) {
        ValidateDataUtil.isNotEmpty(projectId);
        return BaseResponse.success(propertyGroupService.queryAllConstraintAndConstrainedElements(projectId));
    }

    /**
     * 查询实例的分类器（包括泛化的）
     *
     * @param projectId
     * @param instanceId
     * @return
     */
    @Operation(summary = "插槽-查询实例的分类器（包括泛化的）")
    @GetMapping("/slots/queryAllClassifier")
    public BaseResponse<Set<String>> queryAllClassifier(@NotBlank(message = ParamErrorConstants.NO_PROJECT_ID) String projectId, @NotBlank(message = ParamErrorConstants.NO_INSTANCE_ID) String instanceId) {
        return BaseResponse.success(propertyGroupService.queryAllClassifier(projectId, instanceId));
    }

    /**
     * 查询实例某个分类器对应的所有slot
     *
     * @param projectId
     * @param instanceId
     * @param classifierId
     * @return
     */
    @Operation(summary = "插槽-查询实例某个分类器对应的所有slot")
    @GetMapping("/slots/queryInstanceSlots")
    public BaseResponse<List<SlotVo>> queryInstanceSlots(String projectId, String instanceId, String classifierId) {
        return BaseResponse.success(propertyGroupService.queryInstanceSlots(projectId, instanceId, classifierId));
    }

    /**
     * 更新或创建实例下slot的值
     *
     * @param dto
     * @return
     */
    @Operation(summary = "插槽-新建或更新实例下slot的值")
    @PostMapping("/slots/createOrUpdateSlotValue")
    public BaseResponse<ModelResultVo> createOrUpdateSlotValue(@Valid @RequestBody CreateOrUpdateSlotValue dto) {
        return BaseResponse.success(propertyGroupService.createOrUpdateSlotValue(dto));
    }

    /**
     * 根据property创建slot
     *
     * @param dto
     * @return
     */
    @Operation(summary = "插槽-根据property创建slot")
    @PostMapping("/slots/createSlotByProperty")
    public BaseResponse<ModelResultVo> createSlotByProperty(@RequestBody CreateSlotByPropertyDTO dto) {
        return BaseResponse.success(propertyGroupService.createSlotByProperty(dto.getProjectId(), dto.getPropertyId(),
                dto.getParentId()));
    }


    /**
     * 获取展示的taggedValue
     *
     * @param projectId
     * @param instanceId
     * @return
     */
    @Operation(summary = "获取展示的taggedValue")
    @GetMapping("/queryTaggedValues")
    public BaseResponse<List<String>> queryTaggedValues(String projectId, String instanceId) {
        return BaseResponse.success(propertyGroupService.queryTaggedValues(projectId, instanceId));
    }

    /**
     * 获取展示的taggedValue
     *
     * @return
     */
    @Operation(summary = "批量获取展示的taggedValue")
    @PostMapping("/queryTaggedValues/batch")
    public BaseResponse<List<TaggedValueVo>> queryTaggedValues(@RequestBody QueryModelDTO dto) {
        return BaseResponse.success(propertyGroupService.queryTaggedValues(dto.getProjectId(), dto.getInstanceIds()));
    }

    @Operation(summary = "获取展示的tags")
    @GetMapping("/tags")
    public BaseResponse<List<String>> queryTags(String projectId, String instanceId) {
        return BaseResponse.success(propertyGroupService.queryTags(projectId, instanceId));
    }

    /**
     * 属性组-查询属性组可选属性列表
     *
     * @param projectId
     * @param propertyGroupId
     * @return com.huawang.mdesign.model.service.vo.BaseResponse<java.util.List < com.huawang.mdesign.model.service.vo.PropertyInfoVo>>
     * @author xz
     * @date 2022/06/06 15:02
     */
    @Operation(summary = "属性组-查询属性组可选属性列表")
    @GetMapping("/queryPropertyGroupColumns")
    public BaseResponse<List<PropertyInfoVo>> queryPropertyGroupColumns(
            @NotBlank(message = ParamErrorConstants.NO_PROJECT_ID) String projectId,
            @NotBlank(message = ParamErrorConstants.NO_PROPERTY_GROUP_ID) String propertyGroupId) {
        return BaseResponse.success(propertyGroupService.queryPropertyGroupColumns(projectId, propertyGroupId));
    }

    /**
     * 属性组-查询模型属性组
     *
     * @param projectId
     * @param instanceId
     * @return com.huawang.mdesign.model.service.vo.BaseResponse<java.util.List < com.huawang.mdesign.model.service.vo.PropertyGroupVo>>
     * @author xz
     * @date 2022/06/06 15:13
     */
    @Operation(summary = "属性组-查询模型属性组")
    @GetMapping("/queryPropertyGroups")
    public BaseResponse<List<PropertyGroupVo>> queryPropertyGroups(
            @NotBlank(message = ParamErrorConstants.NO_PROJECT_ID) String projectId,
            @NotBlank(message = ParamErrorConstants.NO_INSTANCE_ID) String instanceId) {
        return BaseResponse.success(propertyGroupService.queryPropertyGroups(projectId, instanceId));
    }

    /**
     * 属性组-根据属性组id 查询展示数据
     *
     * @param dto
     * @return com.huawang.mdesign.model.service.vo.BaseResponse<com.huawang.mdesign.model.service.vo.PropertyGroupVo>
     * @author xz
     * @date 2022/06/09 17:53
     */
    @Operation(summary = "属性组-根据属性组id 查询展示数据")
    @PostMapping("/queryPropertyGroupInfo")
    public BaseResponse<PropertyGroupVo> queryPropertyGroupInfo(@Valid @RequestBody QueryPropertyGroupInfoDTO dto) {
        return BaseResponse.success(propertyGroupService.queryRowValues(dto.getProjectId(), dto.getPropertyGroupId(),
                dto.getInstanceId(), dto.getRowIds()));
    }

    @Operation(summary = "属性组-获取当前属性组可展示的属性（属性组的可选行）")
    @GetMapping("/customize/querySelectedProperties")
    public BaseResponse<List<PropertyInfoVo>> queryPropertyGroupSelectedProperties(String projectId, String propertyGroupId) {
        return BaseResponse.success(propertyGroupService.queryPropertyGroupSelectedProperties(projectId, propertyGroupId));
    }

    @Operation(summary = "属性组-获取当前属性组展示模型的可选属性（属性组的可选列）")
    @GetMapping("/customize/querySelectedColumns")
    public BaseResponse<List<PropertyInfoVo>> queryPropertyGroupSelectedColumns(String projectId, String propertyGroupId) {
        return BaseResponse.success(propertyGroupService.queryPropertyGroupSelectedColumns(projectId, propertyGroupId));
    }

    @Operation(summary = "约束-查询某个元素应用的约束")
    @GetMapping("constraints/queryInstanceConstraints")
    public BaseResponse<List<ConstraintVo>> queryInstanceConstraints(@NotBlank(message = ParamErrorConstants.NO_PROJECT_ID) String projectId,
                                                                     @NotBlank(message = ParamErrorConstants.NO_INSTANCE_ID) String instanceId) {
        return BaseResponse.success(propertyGroupService.queryInstanceConstraints(projectId, instanceId));
    }

    @Operation(summary = "约束-新建约束并应用")
    @PostMapping("createConstraintAndApply")
    public BaseResponse<ModelResultVo> createConstraintAndApply(@Valid @RequestBody CreateConstraintsDTO createConstraintsDto) {
        return BaseResponse.success(propertyGroupService.createConstraintAndApply(createConstraintsDto.getProjectId(),
                createConstraintsDto.getInstanceId(), createConstraintsDto.getConstrainType(), createConstraintsDto.getAppliedStereotypes()));
    }


    @Operation(summary = "标签-查询某个元素应用的构造型")
    @GetMapping("/tags/queryAllStereotype")
    public BaseResponse<List<String>> queryAllStereotype(@NotBlank(message = ParamErrorConstants.NO_PROJECT_ID) String projectId,
                                                         @NotBlank(message = ParamErrorConstants.NO_INSTANCE_ID) String instanceId) {
        return BaseResponse.success(propertyGroupService.queryAllStereotype(projectId, instanceId));
    }

    @Operation(summary = "标签-查询某个构造型对应的所有slot")
    @GetMapping("/tags/queryPropertySlots")
    public BaseResponse<List<SlotVo>> queryPropertySlots(String projectId, String instanceId, String stereotypeId) {
        return BaseResponse.success(propertyGroupService.queryPropertySlots(projectId, instanceId, stereotypeId));
    }

    @Operation(summary = "标签-根据property创建slot")
    @PostMapping("/tags/createSlotBasedOnProperty")
    public BaseResponse<ModelResultVo> createSlotBasedOnProperty(@RequestBody CreateSlotByPropertyDTO dto) {
        return BaseResponse.success(propertyGroupService.createSlotBasedOnProperty(dto.getProjectId(),
                dto.getPropertyId(), dto.getParentId()));
    }

    /**
     * 更新或创建实例下slot的值
     *
     * @param dto
     * @return
     */
    @Operation(summary = "标签-直接更新属性值")
    @PostMapping("/slots/updateSlotValue")
    public BaseResponse<ModelResultVo> updateSlotValue(@RequestBody ModifyPropertyDTO dto) {
        return BaseResponse.success(propertyManager.updateValue(dto));
    }

    @Operation(summary = "创建实例规格和插槽并赋值")
    @PostMapping("/createInstanceSpecificationWithSlot")
    public BaseResponse<ModelResultVo> createInstanceSpecificationWithSlot(@RequestBody CreateInstanceSpecificationDTO dto) {
        return BaseResponse.success(propertyGroupService.createInstanceSpecificationWithSlot(dto));
    }

    @Operation(summary = "删除模型下的所有实例")
    @GetMapping("/deleteInstanceSpecificationsUnderOwner")
    public BaseResponse<ModelResultVo> deleteInstanceSpecificationsUnderOwner(String projectId, String ownerId) {
        return BaseResponse.success(propertyGroupService.deleteInstanceSpecificationsUnderOwner(projectId, ownerId));
    }

    /**
     * 查询实例某个分类器对应的所有slot
     *
     * @param projectId
     * @param typeId
     * @return
     */
    @Operation(summary = "插槽-查询实例某个分类器对应的所有slot")
    @GetMapping("/slots/queryTypeSlots")
    public BaseResponse<List<PreviewSlotVo>> queryTypeSlots(String projectId, String typeId) {
        return BaseResponse.success(propertyGroupService.queryTypeSlots(projectId, typeId));
    }

    /**
     * 更新或创建实例下slot的值
     *
     * @param dto
     * @return
     */
    @Operation(summary = "批量创建实例，并设置插槽")
    @PostMapping("/instance/batchCreateInstances")
    public BaseResponse<ModelResultVo> batchCreateInstances(@Valid @RequestBody BatchCreateInstanceDTO dto) {
        return BaseResponse.success(propertyGroupService.batchCreateInstances(dto));
    }

    @Operation(summary = "查询当前模型及子模型应用的约束列表")
    @GetMapping("/queryAllApplyConstraints")
    public BaseResponse<List<String>> queryAllApplyConstraints(String projectId,
                                                               String instanceId) {
        return BaseResponse.success(propertyGroupService.queryAllApplyConstraints(projectId, instanceId));
    }

}
